package main

/*
#include <stdlib.h>

// 回调函数类型定义
typedef void (*StateChangeCallback)(char* state, char* message);
typedef void (*ProgressCallback)(double progress, double speed);
typedef void (*ErrorCallback)(char* error);

// 全局回调函数指针
static StateChangeCallback stateCallback = NULL;
static ProgressCallback progressCallback = NULL;
static ErrorCallback errorCallback = NULL;

// 设置回调函数
static inline void setCallbacks(StateChangeCallback sc, ProgressCallback pc, ErrorCallback ec) {
    stateCallback = sc;
    progressCallback = pc;
    errorCallback = ec;
}

// 调用回调函数
static inline void callStateChange(char* state, char* message) {
    if (stateCallback != NULL) {
        stateCallback(state, message);
    }
}

static inline void callProgress(double progress, double speed) {
    if (progressCallback != NULL) {
        progressCallback(progress, speed);
    }
}

static inline void callError(char* error) {
    if (errorCallback != NULL) {
        errorCallback(error);
    }
}
*/
import "C"

import (
	"fmt"
	"log"
	"net"
	"strings"
	"sync"
	"time"
	"unicode/utf8"
	"unsafe"

	"tunnel_manager/core"
)

// TunnelManager 隧道管理器 - 简化版本
type TunnelManager struct {
	tunnelID   string
	serverAddr string
	targetHost string
	targetPort int

	// 核心组件
	connManager   ConnectionManager
	tunnelHandler TunnelHandler
	errorHandler  ErrorHandler

	// ⚠️ 旧的HTTP/2和多隧道连接池已删除（改用QUIC）
	// http2Pool *HTTP2ConnectionPool
	// useHTTP2  bool // 是否使用HTTP/2

	// connectionPool *TunnelConnectionPool
	useMultiTunnel bool // 是否使用多隧道模式（已废弃）

	// 🚀🚀🚀 QUIC 客户端（最新）
	quicClient *QUICTunnelClient
	useQUIC    bool // 是否使用QUIC

	// 状态管理
	connected bool
	mutex     sync.RWMutex

	// 统计信息
	startTime    time.Time
	lastActivity time.Time
}

// NewTunnelManager 创建隧道管理器
func NewTunnelManager() *TunnelManager {
	return &TunnelManager{
		connManager:    nil,   // ⚠️ 已废弃，QUIC不需要
		errorHandler:   nil,   // ⚠️ 已废弃，QUIC不需要
		useMultiTunnel: false, // 已废弃
		useQUIC:        true,  // 🚀🚀🚀 启用QUIC！性能之王！
		startTime:      time.Now(),
		lastActivity:   time.Now(),
	}
}

// SetMultiTunnelMode 设置多隧道模式
func (tm *TunnelManager) SetMultiTunnelMode(enabled bool) {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()
	tm.useMultiTunnel = enabled
	log.Printf("📝 设置多隧道模式: %v", enabled)
}

// SetHTTP2Mode 设置HTTP/2模式（已废弃）
func (tm *TunnelManager) SetHTTP2Mode(enabled bool) {
	// ⚠️ HTTP/2模式已废弃，改用QUIC
	log.Printf("⚠️ HTTP/2模式已废弃，忽略设置")
}

// Connect 连接到隧道服务器
func (tm *TunnelManager) Connect(tunnelID, serverAddr, targetHost string, targetPort int) error {
	return tm.ConnectWithProtocol(tunnelID, serverAddr, targetHost, targetPort, core.ProtocolHTTP)
}

// ConnectWithProtocol 使用指定协议连接到服务器
func (tm *TunnelManager) ConnectWithProtocol(tunnelID, serverAddr, targetHost string, targetPort int, protocolType core.ProtocolType) error {
	tm.mutex.Lock()
	useQUIC := tm.useQUIC
	tm.mutex.Unlock()

	if tm.connected {
		return fmt.Errorf("隧道已连接")
	}

	// 验证隧道ID编码
	if !utf8.ValidString(tunnelID) {
		return fmt.Errorf("隧道ID包含无效的UTF-8字符")
	}

	tm.tunnelID = tunnelID
	tm.serverAddr = serverAddr
	tm.targetHost = targetHost
	tm.targetPort = targetPort

	// 🚀🚀🚀🚀 QUIC模式（唯一支持的模式）
	if useQUIC {
		log.Printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
		log.Printf("🚀🚀🚀 使用QUIC模式连接服务器！协议=%s", protocolType)
		log.Printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
		return tm.connectQUICWithProtocol(tunnelID, serverAddr, targetHost, targetPort, protocolType)
	}

	// ⚠️ 单隧道模式（向后兼容）
	log.Printf("⚠️ 使用单隧道模式连接服务器（向后兼容）")
	return tm.connectSingleTunnel(tunnelID, serverAddr, targetHost, targetPort)
}

// connectQUIC 建立 QUIC 隧道连接（默认HTTP协议）
func (tm *TunnelManager) connectQUIC(tunnelID, serverAddr, targetHost string, targetPort int) error {
	return tm.connectQUICWithProtocol(tunnelID, serverAddr, targetHost, targetPort, core.ProtocolHTTP)
}

// connectQUICWithProtocol 建立指定协议的 QUIC 隧道连接
func (tm *TunnelManager) connectQUICWithProtocol(tunnelID, serverAddr, targetHost string, targetPort int, protocolType core.ProtocolType) error {
	log.Printf("🔧 创建QUIC客户端... 协议=%s", protocolType)

	// 🔧 将TCP地址转换为QUIC地址（端口9443，UDP）
	// 从 127.0.0.1:9001 转换为 127.0.0.1:9443
	quicAddr := strings.Replace(serverAddr, ":9001", ":9443", 1)
	log.Printf("🔧 QUIC服务器地址: %s (从 %s 转换)", quicAddr, serverAddr)

	// 转换目标端口为字符串
	targetPortStr := fmt.Sprintf("%d", targetPort)

	// 创建 QUIC 客户端（带协议类型）
	client, err := NewQUICTunnelClient(quicAddr, tunnelID, protocolType, targetHost, targetPortStr)
	if err != nil {
		return fmt.Errorf("创建QUIC客户端失败: %v", err)
	}

	// 连接到服务端
	log.Printf("🔗 连接到QUIC服务器: %s", quicAddr)
	if err := client.Connect(); err != nil {
		return fmt.Errorf("连接QUIC服务器失败: %v", err)
	}

	// 保存客户端
	tm.mutex.Lock()
	tm.quicClient = client
	tm.connected = true
	tm.mutex.Unlock()

	protocolName := "HTTP"
	if protocolType == ProtocolTCP {
		protocolName = "TCP"
	}

	log.Printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
	log.Printf("✨ 🎉 QUIC %s 隧道连接成功！🎉 ✨", protocolName)
	log.Printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
	log.Printf("")
	log.Printf("📊 性能优势:")
	log.Printf("   ✅ 连接延迟: 0-RTT (vs TCP: 3-RTT)")
	log.Printf("   ✅ 丢包恢复: 独立Stream (vs TCP: 全局阻塞)")
	log.Printf("   ✅ 网络切换: 无缝迁移 (vs TCP: 断开重连)")
	log.Printf("   ✅ 并发能力: 10000+ Streams")
	log.Printf("")
	log.Printf("🔧 连接信息:")
	log.Printf("   ├─ 隧道ID: %s", tunnelID[:8]+"...")
	log.Printf("   ├─ 服务端: %s", serverAddr)
	log.Printf("   ├─ 目标: %s:%d", targetHost, targetPort)
	log.Printf("   ├─ 协议类型: %s", protocolName)
	log.Printf("   └─ 传输协议: QUIC + TLS 1.3")
	log.Printf("")
	log.Printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")

	return nil
}

// connectMultiTunnel 建立多隧道连接（双通道模式）
// ⚠️ 已废弃：改用QUIC
func (tm *TunnelManager) connectMultiTunnel(tunnelID, serverAddr, targetHost string, targetPort int) error {
	return fmt.Errorf("多隧道模式已废弃，请使用QUIC")
}

// connectSingleTunnel 建立单隧道连接（向后兼容）
// ⚠️ 已废弃：改用QUIC
func (tm *TunnelManager) connectSingleTunnel(tunnelID, serverAddr, targetHost string, targetPort int) error {
	return fmt.Errorf("单隧道模式已废弃，请使用QUIC")
}

// handleTunnelData 处理隧道数据
func (tm *TunnelManager) handleTunnelData(conn net.Conn) {
	defer func() {
		conn.Close()
		tm.mutex.Lock()
		tm.connected = false
		tm.mutex.Unlock()
		log.Printf("🔌 隧道连接已关闭: %s", tm.tunnelID)
	}()

	for {
		err := tm.tunnelHandler.HandleConnection(conn, tm.tunnelID)
		if err != nil {
			log.Printf("❌ 隧道数据处理失败: %v", err)
			break
		}
	}
}

// connectHTTP2 使用HTTP/2混合模式连接服务器
//
// 🔥 混合模式设计：
// 1. TCP隧道连接池：接收HTTP请求（服务端推送，30个并发连接）
// 2. HTTP/2客户端：发送HTTP响应（高并发，1000+ Stream）
//
// 优势：
// - 保持现有TCP架构兼容性
// - 充分利用HTTP/2多路复用能力
// - 响应发送可达1000+并发
// - TCP连接池提供30个并发接收能力
// ⚠️ 已废弃：改用QUIC
func (tm *TunnelManager) connectHTTP2(tunnelID, serverAddr, targetHost string, targetPort int) error {
	return fmt.Errorf("HTTP/2模式已废弃，请使用QUIC")
}

// Disconnect 断开隧道连接
func (tm *TunnelManager) Disconnect() error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	log.Printf("🔌 开始断开连接: tunnelID=%s, connected=%v, quicClient=%v",
		tm.tunnelID, tm.connected, tm.quicClient != nil)

	// 🔥🔥🔥 关键修复：无条件执行断开流程
	// 问题场景：
	// 1. Connect()异步建立连接，可能超时返回error
	// 2. connectionPool被设置为nil
	// 3. 但后台goroutine还在建立连接，连接最终建立成功
	// 4. 这些连接对象在内存中运行，但connectionPool指针是nil
	// 5. Disconnect()检查connectionPool==nil就跳过，导致连接泄漏
	//
	// 解决方案：
	// 1. 不再检查connectionPool是否为nil
	// 2. 总是调用Close()，Close()内部会检查started状态
	// 3. 确保所有连接都被关闭

	closedAny := false
	var lastErr error

	// 0. 关闭 QUIC 客户端（最优先）
	if tm.quicClient != nil {
		log.Printf("🔌 关闭QUIC客户端...")
		if err := tm.quicClient.Close(); err != nil {
			log.Printf("⚠️ 关闭QUIC客户端失败: %v", err)
			lastErr = err
		}
		tm.quicClient = nil
		log.Printf("✅ QUIC客户端已关闭: %s", tm.tunnelID)
		closedAny = true
	} else {
		log.Printf("⏭️ QUIC客户端已为nil，跳过关闭")
	}

	// ⚠️ HTTP/2和TCP隧道连接池已废弃
	// if tm.http2Pool != nil {
	// 	tm.http2Pool.Close()
	// 	tm.http2Pool = nil
	// }
	// if tm.connectionPool != nil {
	// 	tm.connectionPool.Close()
	// 	tm.connectionPool = nil
	// }

	// ⚠️ 旧的TCP隧道连接池已废弃
	// if tm.connectionPool != nil {
	// 	tm.connectionPool.Close()
	// 	tm.connectionPool = nil
	// }

	// 标记为断开状态
	tm.connected = false

	if closedAny {
		log.Printf("✅ 隧道断开连接完成: %s", tm.tunnelID)
	} else {
		log.Printf("⚠️ 隧道已经断开，无需操作: %s", tm.tunnelID)
	}

	return lastErr
}

// IsConnected 检查连接状态
func (tm *TunnelManager) IsConnected() bool {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()
	return tm.connected
}

// GetStats 获取统计信息
func (tm *TunnelManager) GetStats() map[string]interface{} {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	stats := map[string]interface{}{
		"connected":     tm.connected,
		"tunnel_id":     tm.tunnelID,
		"server_addr":   tm.serverAddr,
		"target_host":   tm.targetHost,
		"target_port":   tm.targetPort,
		"start_time":    tm.startTime,
		"last_activity": tm.lastActivity,
		"multi_tunnel":  tm.useMultiTunnel,
	}

	// ⚠️ 多隧道统计信息已废弃
	// if tm.connectionPool != nil {
	// 	poolStats := tm.connectionPool.GetStats()
	// 	stats["pool"] = poolStats
	// }

	return stats
}

// 全局隧道管理器实例
var globalTunnelManager *TunnelManager

// safeGoString 安全地将C字符串转换为Go字符串
func safeGoString(cstr *C.char) (string, error) {
	if cstr == nil {
		return "", fmt.Errorf("C字符串指针为空")
	}

	// 使用defer捕获可能的panic
	var result string
	var err error

	func() {
		defer func() {
			if r := recover(); r != nil {
				err = fmt.Errorf("C字符串转换失败: %v", r)
			}
		}()
		result = C.GoString(cstr)
	}()

	return result, err
}

// C export 函数 - 动态库接口

//export SetCallbacks
func SetCallbacks(stateCallback, progressCallback, errorCallback unsafe.Pointer) {
	C.setCallbacks(C.StateChangeCallback(stateCallback), C.ProgressCallback(progressCallback), C.ErrorCallback(errorCallback))
}

//export CreateAndConnectTunnel
func CreateAndConnectTunnel(tunnelID, serverHost *C.char, serverPort C.int, targetHost *C.char, targetPort C.int) C.int {
	log.Printf("🔗 开始创建隧道连接...")

	// 使用安全的字符串转换
	goTunnelID, err := safeGoString(tunnelID)
	if err != nil {
		log.Printf("❌ tunnelID转换失败: %v", err)
		return 0
	}

	goServerHost, err := safeGoString(serverHost)
	if err != nil {
		log.Printf("❌ serverHost转换失败: %v", err)
		return 0
	}

	goTargetHost, err := safeGoString(targetHost)
	if err != nil {
		log.Printf("❌ targetHost转换失败: %v", err)
		return 0
	}

	goServerPort := int(serverPort)
	goTargetPort := int(targetPort)

	// 组合服务器地址
	goServerAddr := fmt.Sprintf("%s:%d", goServerHost, goServerPort)

	log.Printf("🔗 隧道参数: tunnelID=%s, server=%s, target=%s:%d",
		goTunnelID, goServerAddr, goTargetHost, goTargetPort)

	if globalTunnelManager == nil {
		globalTunnelManager = NewTunnelManager()
	}

	// 🔥 防止重复连接：如果已经连接，直接返回成功
	if globalTunnelManager.IsConnected() {
		log.Printf("⚠️ 隧道已连接，跳过重复连接请求")
		return 1
	}

	// 🔥🔥🔥 关键优化：异步连接，立即返回，不阻塞Flutter UI
	// 原问题：同步调用 Connect() 会阻塞 1-2 秒等待第一批连接建立，导致 UI 卡顿
	// 解决方案：在后台 goroutine 中异步建立连接，FFI 函数立即返回
	//
	// ⚠️ 注意：不能在 goroutine 中调用 Dart 回调！
	// 原因：Dart 回调必须在 Dart isolate 中运行，Go goroutine 不在 isolate 中
	// 解决：Flutter 端通过轮询 IsConnected() 来检测连接状态
	go func() {
		log.Printf("🚀 [异步连接] 开始建立隧道连接...")
		err := globalTunnelManager.Connect(goTunnelID, goServerAddr, goTargetHost, goTargetPort)
		if err != nil {
			log.Printf("❌ [异步连接] 隧道连接失败: %v", err)
			// ⚠️ 不能在这里调用回调，会导致 "Cannot invoke native callback outside an isolate" 错误
			// Flutter 端会通过轮询 IsConnected() 来检测失败
			return
		}

		log.Printf("✅ [异步连接] 隧道连接建立成功")
		// ⚠️ 不能在这里调用回调
		// Flutter 端会通过轮询 IsConnected() 来检测成功
	}()

	log.Printf("✅ 隧道连接正在后台建立（UI 不会被阻塞）")
	return 1 // 立即返回成功（连接正在后台进行）
}

//export ConnectTunnel
func ConnectTunnel(tunnelID, serverHost *C.char, serverPort C.int, targetHost *C.char, targetPort C.int) C.int {
	return CreateAndConnectTunnel(tunnelID, serverHost, serverPort, targetHost, targetPort)
}

//export ConnectTCPTunnel
func ConnectTCPTunnel(tunnelID, serverHost *C.char, serverPort C.int, targetHost *C.char, targetPort C.int) C.int {
	log.Printf("🔌 [TCP隧道] 开始创建TCP隧道连接...")

	// 使用安全的字符串转换
	goTunnelID, err := safeGoString(tunnelID)
	if err != nil {
		log.Printf("❌ tunnelID转换失败: %v", err)
		return 0
	}

	goServerHost, err := safeGoString(serverHost)
	if err != nil {
		log.Printf("❌ serverHost转换失败: %v", err)
		return 0
	}

	goTargetHost, err := safeGoString(targetHost)
	if err != nil {
		log.Printf("❌ targetHost转换失败: %v", err)
		return 0
	}

	goServerPort := int(serverPort)
	goTargetPort := int(targetPort)

	// 组合服务器地址
	goServerAddr := fmt.Sprintf("%s:%d", goServerHost, goServerPort)

	log.Printf("🔌 [TCP隧道] 参数: tunnelID=%s, server=%s, target=%s:%d",
		goTunnelID, goServerAddr, goTargetHost, goTargetPort)

	if globalTunnelManager == nil {
		globalTunnelManager = NewTunnelManager()
	}

	// 防止重复连接
	if globalTunnelManager.IsConnected() {
		log.Printf("⚠️ 隧道已连接，跳过重复连接请求")
		return 1
	}

	// 异步连接
	go func() {
		log.Printf("🚀 [TCP隧道异步连接] 开始建立TCP隧道...")
		err := globalTunnelManager.ConnectWithProtocol(goTunnelID, goServerAddr, goTargetHost, goTargetPort, core.ProtocolTCP)
		if err != nil {
			log.Printf("❌ [TCP隧道异步连接] 连接失败: %v", err)
			return
		}
		log.Printf("✅ [TCP隧道异步连接] TCP隧道已成功建立！")
	}()

	log.Printf("✅ [TCP隧道] FFI函数立即返回（连接正在后台进行）")
	return 1
}

//export DisconnectTunnel
func DisconnectTunnel() C.int {
	log.Printf("🔌 [FFI] 收到断开连接请求")
	log.Printf("🔌 [FFI] globalTunnelManager = %v", globalTunnelManager)

	if globalTunnelManager == nil {
		log.Printf("❌ [FFI] 断开失败: globalTunnelManager 为 nil")
		return 0
	}

	// 断开前检查状态
	isConnectedBefore := globalTunnelManager.IsConnected()
	log.Printf("🔌 [FFI] 断开前状态: connected=%v", isConnectedBefore)

	log.Printf("🔌 [FFI] 调用 globalTunnelManager.Disconnect()...")
	err := globalTunnelManager.Disconnect()
	if err != nil {
		log.Printf("❌ [FFI] 断开隧道失败: %v", err)
		return 0
	}

	// 断开后检查状态
	isConnectedAfter := globalTunnelManager.IsConnected()
	log.Printf("🔌 [FFI] 断开后状态: connected=%v", isConnectedAfter)

	if isConnectedAfter {
		log.Printf("⚠️ [FFI] 警告: 断开后状态仍为connected，这不应该发生！")
	}

	log.Printf("✅ [FFI] 隧道已成功断开")
	return 1
}

//export IsConnected
func IsConnected() C.int {
	if globalTunnelManager == nil {
		return 0
	}

	if globalTunnelManager.IsConnected() {
		return 1
	}
	return 0
}

//export GetConnectionStats
func GetConnectionStats() *C.char {
	if globalTunnelManager == nil {
		return C.CString("{\"error\": \"tunnel manager not initialized\"}")
	}

	stats := globalTunnelManager.GetStats()
	statsStr := fmt.Sprintf(`{
		"connected": %t,
		"tunnel_id": "%s",
		"server_addr": "%s",
		"target_host": "%s",
		"target_port": %d
	}`, stats["connected"], stats["tunnel_id"], stats["server_addr"],
		stats["target_host"], stats["target_port"])

	return C.CString(statsStr)
}

//export GetVersion
func GetVersion() *C.char {
	return C.CString("1.0.0-simplified")
}

//export SetLogLevel
func SetLogLevel(level *C.char) {
	logLevel, err := safeGoString(level)
	if err != nil {
		log.Printf("❌ 日志级别转换失败: %v", err)
		return
	}

	log.Printf("📋 设置日志级别: %s", logLevel)
}

//export GetStats
func GetStats() *C.char {
	return GetConnectionStats()
}

//export DestroyManager
func DestroyManager() {
	if globalTunnelManager != nil {
		globalTunnelManager.Disconnect()
		globalTunnelManager = nil
	}
}

func main() {
	// 动态库不需要main函数，但Go要求必须有
}
